#include <dde_kit/semaphore.h>

#include <eku/proc.h>
#include <eku/sync.h>
#include <eku/stdlib.h>
#include <eku/symbol.h>

struct dde_kit_sem
{
	 semaphore_t sem;
};

/**
 * Initialize DDE kit semaphore
 *
 * \param  value  initial semaphore counter
 *
 * \return        pointer to new semaphore
 */
dde_kit_sem_t *
dde_kit_sem_init(int value)
{
	 dde_kit_sem_t *result = (dde_kit_sem_t *)malloc(sizeof(struct dde_kit_sem));
	 if (result == NULL)
	 {
		  return NULL;
	 }
	 semaphore_init(&result->sem, value);
	 // dde_kit_printf("create sem %08x, value = %d!\n", result->sem, value);
	 return result;
}

/**
 * Deinitialize semaphore
 *
 * \param  sem  semaphore reference
 */
void
dde_kit_sem_deinit(dde_kit_sem_t *sem)
{
	 // dde_kit_printf("deinit sem %08x\n", sem->sem);
	 free(sem);
}

/**
 * Acquire semaphore
 *
 * \param  sem  semaphore reference
 */
void
dde_kit_sem_down(dde_kit_sem_t *sem)
{
	 // dde_kit_printf("down sem %08x!\n", sem->sem);
	 uips_node_t node;
	 if (semaphore_acquire(&sem->sem, &node))
		  uips_wait(&node);
}

/**
 * Acquire semaphore (non-blocking)
 *
 * \param  sem  semaphore reference
 *
 * \return      semaphore state
 * \retval 0    semaphore was acquired
 * \retval !=0  semaphore was not acquired
 */
int
dde_kit_sem_down_try(dde_kit_sem_t *sem)
{
	 return semaphore_try_acquire(&sem->sem);
}

/**
 * Acquire semaphore (with timeout)
 *
 * \param  sem      semaphore reference
 * \param  timeout  timeout (in ms)
 *
 * \return          semaphore state
 * \retval 0        semaphore was acquired
 * \retval !=0      semaphore was not acquired
 */
//int dde_kit_sem_down_timed(dde_kit_sem_t *sem, int timout);

/**
 * Release semaphore
 *
 * \param  sem  semaphore reference
 */
void
dde_kit_sem_up(dde_kit_sem_t *sem)
{
	 // dde_kit_printf("up sem %08x!\n", sem->sem);
	 semaphore_release(&sem->sem);
}

void
dde_kit_sem_symbol(void)
{
	 export_symbol("dde_kit_sem_init", &dde_kit_sem_init, 1);
	 export_symbol("dde_kit_sem_deinit", &dde_kit_sem_deinit, 1);
	 export_symbol("dde_kit_sem_down", &dde_kit_sem_down, 1);
	 export_symbol("dde_kit_sem_down_try", &dde_kit_sem_down_try, 1);
	 export_symbol("dde_kit_sem_up", &dde_kit_sem_up, 1);
}
